import { SOCKETURL } from './config'
import store from '@/store'

class Socket {
	constructor() {
		this.count = 0 // 响应数量
		this.reconnectNumber = 0 // 重连数量
		this.socketStart = false // 连接开始
		this.monitorSocketError()
		this.monitorSocketClose()
		this.socketReceive()
	}
	async init(callback) {
		if (SOCKETURL) {
			if (this.socketStart) {
				console.log('webSocket已经启动了')
			} else {
				let socket = await uni.connectSocket({
					url: SOCKETURL,
					method: 'GET',
					protocols: [store.user.userData.access_token],
					success() {
						console.log('连接成功')
					}
				})
				socket.onOpen(() => {
					// 连接后开始心跳
					const timer = setTimeout(() => {
						clearTimeout(timer)
						this.getHeartbeat()
					}, 1000)
					this.count = 0
					this.socketStart = true
					this.reconnectNumber = 0
					callback && callback()
					console.log('连接打开，开始心跳')
				})
			}
		} else {
			console.log('CONFIG SOCKETURL为空')
		}
	}
	// Socket给服务器发送消息
	send(data, callback) {
		uni.sendSocketMessage({
			data: JSON.stringify(data),
			success: () => {
				callback && callback(++this.count)
			},
			fail: () => {
				callback && callback(false)
			}
		})
	}
	// Socket接收服务器发送过来的消息
	socketReceive() {
		uni.onSocketMessage(res => {
			const data = JSON.parse(res.data)
			// 是否显示错误消息
			if (data.is_display == 1) {
				uni.showToast({
					icon: 'none',
					duration: 3000,
					title: data.msg
				})
			}
			// 收到消息
			if (data.cmd_event == 'system.event') {
				store.state.setMessage(data.data)
			}
			// 调用监听函数
			if (this.acceptMessage) {
				this.acceptMessage(data)
			}
			this.count = 0
		})
	}
	// 关闭Socket
	closeSocket(callback) {
		this.count = 0
		uni.closeSocket({
			success: () => {
				callback && callback(true)
			},
			fail: () => {
				callback && callback(false)
			}
		})
	}
	// 监听Socket关闭
	monitorSocketClose() {
		uni.onSocketClose(() => {
			this.socketStart = false
		})
	}
	// 监听Socket错误
	monitorSocketError() {
		uni.onSocketError(res => {
			this.count++
			this.socketStart = false
			if (res.errMsg.includes('401')) {
				store.user.logout()
			}
			if (this.count < 10) {
				const timer = setTimeout(() => {
					this.init()
					clearTimeout(timer)
				}, 3000)
			} else {
				uni.showToast({
					icon: 'none',
					duration: 3000,
					title: '网络波动较大,请稍后重试~'
				})
			}
			console.log('监听Socket错误', res)
		})
	}
	// 心跳
	getHeartbeat() {
		this.send(
			{
				ext: {},
				data: {},
				cmd_event: 'user.ping'
			},
			res => {
				// 发送失败直接重连
				if (!res) {
					// 重连超过10次失败则提示稍后重试~
					if (this.reconnectNumber > 10) {
						uni.showToast({
							icon: 'none',
							duration: 3000,
							title: '网络波动较大,请稍后重试~'
						})
						return
					}
					this.socketStart = false
					this.reconnectNumber++
					this.init()
					return
				}
				const timer = setTimeout(() => {
					if (res < 3) {
						// 服务器有响应继续心跳
						this.getHeartbeat()
					} else if (this.socketStart) {
						// 发送成功，超过三次没响应重连
						// 重连超过10次无响应则提示稍后重试~
						if (this.reconnectNumber > 10) {
							uni.showToast({
								icon: 'none',
								duration: 3000,
								title: '网络波动较大,请稍后重试~'
							})
							return
						}
						this.socketStart = false
						this.reconnectNumber++
						this.init()
					}
					clearTimeout(timer)
				}, 10000)
			}
		)
	}
}

export const socket = new Socket()
